home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SunSoft Catalyst CDWARE 1996 May to August
/
Catalyst CDWARE 1996 May to August.iso
/
.products
/
.bin
/
httpd
/
src
/
http_config.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-18
|
36KB
|
1,036 lines
/*
* http_config.c: auxillary functions for reading httpd's config file
* and converting filenames into a namespace
*
* All code contained herein is covered by the Copyright as distributed
* in the README file in the main directory of the distribution of
* NCSA HTTPD.
*
* Based on NCSA HTTPd 1.3 by Rob McCool
*
* 10/28/94 cvarela
* Added config options AgentLog and RefererLog for extra log info
*
* 02/19/95 blong
* Added config options MaxServers and StartServers for configuration
* defined children
*
* 03/21/95 cvarela
* Added RefererIgnore to ignore certain URIs when logging referers
*/
#include "httpd.h"
#include "new.h"
/* Server config globals */
int standalone;
int port;
uid_t user_id;
gid_t group_id;
char server_root[MAX_STRING_LEN];
char error_fname[MAX_STRING_LEN];
char xfer_fname[MAX_STRING_LEN];
char agent_fname[MAX_STRING_LEN];
char referer_fname[MAX_STRING_LEN];
char referer_ignore[MAX_STRING_LEN];
char pid_fname[MAX_STRING_LEN];
char server_admin[MAX_STRING_LEN];
char *server_hostname;
char srm_confname[MAX_STRING_LEN];
char server_confname[MAX_STRING_LEN];
char access_confname[MAX_STRING_LEN];
char types_confname[MAX_STRING_LEN];
char annotation_server[MAX_STRING_LEN]; /* SSG 4/5/95 annotation server url */
int timeout;
int do_rfc931;
#ifndef NO_PASS
int max_servers;
int start_servers;
#endif
void process_server_config(FILE *errors) {
FILE *cfg;
char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
int n=0;
standalone = 1;
port = DEFAULT_PORT;
user_id = uname2id(DEFAULT_USER);
group_id = gname2id(DEFAULT_GROUP);
#ifndef NO_PASS
max_servers = DEFAULT_MAX_DAEMON;
start_servers = DEFAULT_START_DAEMON;
#endif
/* ServerRoot set in httpd.c */
make_full_path(server_root,DEFAULT_ERRORLOG,error_fname);
make_full_path(server_root,DEFAULT_XFERLOG,xfer_fname);
make_full_path(server_root,DEFAULT_AGENTLOG,agent_fname);
make_full_path(server_root,DEFAULT_REFERERLOG,referer_fname);
make_full_path(server_root,DEFAULT_PIDLOG,pid_fname);
strcpy(referer_ignore,DEFAULT_REFERERIGNORE);
strcpy(server_admin,DEFAULT_ADMIN);
server_hostname = NULL;
make_full_path(server_root,RESOURCE_CONFIG_FILE,srm_confname);
/* server_confname set in httpd.c */
make_full_path(server_root,ACCESS_CONFIG_FILE,access_confname);
make_full_path(server_root,TYPES_CONFIG_FILE,types_confname);
/* initialize the ann.server to nothing */
annotation_server[0] = '\0';
timeout = DEFAULT_TIMEOUT;
do_rfc931 = DEFAULT_RFC931;
if(!(cfg = fopen(server_confname,"r"))) {
fprintf(errors,"httpd: could not open server config. file %s\n",server_confname);
perror("fopen");
exit(1);
}
/* Parse server config file. Remind me to learn yacc. */
while(!(cfg_getline(l,MAX_STRING_LEN,cfg))) {
++n;
if((l[0] != '#') && (l[0] != '\0')) {
cfg_getword(w,l);
if(!strcasecmp(w,"ServerType")) {
if(!strcasecmp(l,"inetd")) standalone=0;
else if(!strcasecmp(l,"standalone")) standalone=1;
else {
fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
fprintf(errors,"ServerType is either inetd or standalone.\n");
exit(1);
}
}
else if(!strcasecmp(w,"Port")) {
cfg_getword(w,l);
port = atoi(w);
}
else if(!strcasecmp(w,"User")) {
cfg_getword(w,l);
user_id = uname2id(w);
}
else if(!strcasecmp(w,"Group")) {
cfg_getword(w,l);
group_id = gname2id(w);
}
else if(!strcasecmp(w,"ServerAdmin")) {
cfg_getword(w,l);
strcpy(server_admin,w);
}
/* SSG-4/4/95 read annotation server directive */
else if(!strcasecmp(w,"Annotation-Server")) {
cfg_getword(w,l);
strcpy(annotation_server, w);
}
else if(!strcasecmp(w,"ServerName")) {
cfg_getword(w,l);
if(server_hostname)
free(server_hostname);
if(!(server_hostname = strdup(w)))
die(NO_MEMORY,"process_resource_config",errors);
}
else if(!strcasecmp(w,"ServerRoot")) {
cfg_getword(w,l);
if(!is_directory(w)) {
fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
fprintf(errors,"%s is not a valid directory.\n",w);
exit(1);
}
strcpy(server_root,w);
make_full_path(server_root,DEFAULT_ERRORLOG,error_fname);
make_full_path(server_root,DEFAULT_XFERLOG,xfer_fname);
make_full_path(server_root,DEFAULT_AGENTLOG,agent_fname);
make_full_path(server_root,DEFAULT_REFERERLOG,referer_fname);
make_full_path(server_root,DEFAULT_PIDLOG,pid_fname);
make_full_path(server_root,RESOURCE_CONFIG_FILE,srm_confname);
make_full_path(server_root,ACCESS_CONFIG_FILE,access_confname);
make_full_path(server_root,TYPES_CONFIG_FILE,types_confname);
}
else if(!strcasecmp(w,"ErrorLog")) {
cfg_getword(w,l);
if(w[0] != '/')
make_full_path(server_root,w,error_fname);
else
strcpy(error_fname,w);
}
else if(!strcasecmp(w,"TransferLog")) {
cfg_getword(w,l);
if(w[0] != '/')
make_full_path(server_root,w,xfer_fname);
else strcpy(xfer_fname,w);
}
else if(!strcasecmp(w,"AgentLog")) {
cfg_getword(w,l);
if(w[0] != '/')
make_full_path(server_root,w,agent_fname);
else strcpy(agent_fname,w);
}
else if(!strcasecmp(w,"RefererLog")) {
cfg_getword(w,l);
if(w[0] != '/')
make_full_path(server_root,w,referer_fname);
else strcpy(referer_fname,w);
}
else if(!strcasecmp(w,"RefererIgnore")) {
cfg_getword(w,l);
strcpy(referer_ignore,w);
}
else if(!strcasecmp(w,"PidFile")) {
cfg_getword(w,l);
if(w[0] != '/')
make_full_path(server_root,w,pid_fname);
else strcpy(pid_fname,w);
}
else if(!strcasecmp(w,"AccessConfig")) {
cfg_getword(w,l);
if(w[0] != '/')
make_full_path(server_root,w,access_confname);
else strcpy(access_confname,w);
}
else if(!strcasecmp(w,"ResourceConfig")) {
cfg_getword(w,l);
if(w[0] != '/')
make_full_path(server_root,w,srm_confname);
else strcpy(srm_confname,w);
}
else if(!strcasecmp(w,"TypesConfig")) {
cfg_getword(w,l);
if(w[0] != '/')
make_full_path(server_root,w,types_confname);
else strcpy(types_confname,w);
}
else if(!strcasecmp(w,"Timeout"))
timeout = atoi(l);
else if(!strcasecmp(w,"IdentityCheck")) {
cfg_getword(w,l);
if(!strcasecmp(w,"on"))
do_rfc931 = 1;
else if(!strcasecmp(w,"off"))
do_rfc931 = 0;
else {
fprintf(errors,"Syntax error on line %d of %s:\n",n,
server_confname);
fprintf(errors,"IdentityCheck must be on or off.\n");
}
}
else if(!strcasecmp(w,"MaxServers")) {
#ifndef NO_PASS
max_servers = atoi(l);
#else
fprintf(errors,"This compile doesn't support MaxServers on line %d of %s:\n",n,server_confname);
#endif
}
else if(!strcasecmp(w,"StartServers")) {
#ifndef NO_PASS
start_servers = atoi(l);
#else
fprintf(errors,"This compile doesn't support StartServers on line %d of %s:\n",n,server_confname);
#endif
}
else {
fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
fprintf(errors,"Unknown keyword %s.\n",w);
exit(1);
}
}
}
fclose(cfg);
}
/* Document config globals */
char user_dir[MAX_STRING_LEN];
char index_name[MAX_STRING_LEN];
char access_name[MAX_STRING_LEN];
char document_root[MAX_STRING_LEN];
char default_type[MAX_STRING_LEN];
char local_default_type[MAX_STRING_LEN];
char default_icon[MAX_STRING_LEN];
char local_default_icon[MAX_STRING_LEN];
void process_resource_config(FILE *errors) {
FILE *cfg;
char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
int n=0;
strcpy(user_dir,DEFAULT_USER_DIR);
strcpy(index_name,DEFAULT_INDEX);
strcpy(access_name,DEFAULT_ACCESS_FNAME);
strcpy(document_root,DOCUMENT_LOCATION);
strcpy(default_type,DEFAULT_TYPE);
default_icon[0] = '\0';
add_opts_int(0,"/",errors);
if(!(cfg = fopen(srm_confname,"r"))) {
fprintf(errors,"httpd: could not open document config. file %s\n",
srm_confname);
perror("fopen");
exit(1);
}
while(!(cfg_getline(l,MAX_STRING_LEN,cfg))) {
++n;
if((l[0] != '#') && (l[0] != '\0')) {
cfg_getword(w,l);
if(!strcasecmp(w,"ScriptAlias")) {
char w2[MAX_STRING_LEN];
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0')) {
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(errors,
"ScriptAlias must be followed by a fakename, one space, then a realname.\n");
exit(1);
}
add_alias(w,w2,SCRIPT_CGI);
}
else if(!strcasecmp(w,"OldScriptAlias")) {
char w2[MAX_STRING_LEN];
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0')) {
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(errors,
"ScriptAlias must be followed by a fakename, one space, then a realname.\n");
exit(1);
}
add_alias(w,w2,SCRIPT_NCSA);
}
else if(!strcasecmp(w,"UserDir")) {
cfg_getword(w,l);
if(!strcmp(w,"DISABLED"))
user_dir[0] = '\0';
else
strcpy(user_dir,w);
}
else if(!strcasecmp(w,"DirectoryIndex")) {
cfg_getword(w,l);
strcpy(index_name,w);
}
else if(!strcasecmp(w,"DefaultType")) {
cfg_getword(w,l);
strcpy(default_type,w);
}
else if(!strcasecmp(w,"AccessFileName")) {
cfg_getword(w,l);
strcpy(access_name,w);
}
else if(!strcasecmp(w,"DocumentRoot")) {
cfg_getword(w,l);
if(!is_directory(w)) {
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(errors,"%s is not a valid directory.\n",w);
exit(1);
}
strcpy(document_root,w);
}
else if(!strcasecmp(w,"Alias")) {
char w2[MAX_STRING_LEN];
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0')) {
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(errors,
"Alias must be followed by a fakename, one space, then a realname.\n");
exit(1);
}
add_alias(w,w2,STD_DOCUMENT);
}
else if(!strcasecmp(w,"AddType")) {
char w2[MAX_STRING_LEN];
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0')) {
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(errors,
"AddType must be followed by a type, one space, then a file or extension.\n");
exit(1);
}
add_type(w2,w,errors);
}
else if(!strcasecmp(w,"AddEncoding")) {
char w2[MAX_STRING_LEN];
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0')) {
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(errors,
"AddEncoding must be followed by a type, one space, then a file or extension.\n");
exit(1);
}
add_encoding(w2,w,errors);
}
else if(!strcasecmp(w,"Redirect")) {
char w2[MAX_STRING_LEN];
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(errors,
"Redirect must be followed by a document, one space, then a URL.\n");
exit(1);
}
add_redirect(w,w2);
}
else if(!strcasecmp(w,"FancyIndexing")) {
cfg_getword(w,l);
if(!strcmp(w,"on"))
add_opts_int(FANCY_INDEXING,"/",errors);
else if(!strcmp(w,"off"))
add_opts_int(0,"/",errors);
else {
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(errors,"FancyIndexing must be on or off.\n");
exit(1);
}
}
else if(!strcasecmp(w,"AddDescription")) {
char desc[MAX_STRING_LEN];
int fq;
if((fq = ind(l,'\"')) == -1) {
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(errors,"AddDescription must have quotes around the description.\n");
exit(1);
}
else {
getword(desc,&l[++fq],'\"');
cfg_getword(w,&l[fq]);
add_desc(BY_PATH,desc,w,"/",errors);
}
}
else if(!strcasecmp(w,"IndexIgnore")) {
while(l[0]) {
cfg_getword(w,l);
add_ignore(w,"/",errors);
}
}
else if(!strcasecmp(w,"AddIcon")) {
char w2[MAX_STRING_LEN];
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_icon(BY_PATH,w2,w,"/",errors);
}
}
else if(!strcasecmp(w,"AddIconByType")) {
char w2[MAX_STRING_LEN];
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_icon(BY_TYPE,w2,w,"/",errors);
}
}
else if(!strcasecmp(w,"AddIconByEncoding")) {
char w2[MAX_STRING_LEN];
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_icon(BY_ENCODING,w2,w,"/",errors);
}
}
else if(!strcasecmp(w,"AddAlt")) {
char w2[MAX_STRING_LEN];
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_alt(BY_PATH,w2,w,"/",errors);
}
}
else if(!strcasecmp(w,"AddAltByType")) {
char w2[MAX_STRING_LEN];
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_alt(BY_TYPE,w2,w,"/",errors);
}
}
else if(!strcasecmp(w,"AddAltByEncoding")) {
char w2[MAX_STRING_LEN];
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_alt(BY_ENCODING,w2,w,"/",errors);
}
}
else if(!strcasecmp(w,"DefaultIcon")) {
cfg_getword(w,l);
strcpy(default_icon,w);
}
else if(!strcasecmp(w,"ReadmeName")) {
cfg_getword(w,l);
add_readme(w,"/",errors);
}
else if(!strcasecmp(w,"HeaderName")) {
cfg_getword(w,l);
add_header(w,"/",errors);
}
else if(!strcasecmp(w,"IndexOptions"))
add_opts(l,"/",errors);
else if (!strcasecmp(w,"ErrorDocument")) {
char w2[MAX_STRING_LEN];
cfg_getword(w,l); /* Get errornum */
cfg_getword(w2,l); /* Get filename */
add_error(w,w2);
}
else {
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(errors,"Unknown keyword %s.\n",w);
exit(1);
}
}
}
fclose(cfg);
Saved_Forced = forced_types;
Saved_Encoding = encoding_types;
/* Save the number of global aliases */
save_aliases();
}
/* Auth Globals */
char *auth_type;
char *auth_name;
char *auth_pwfile;
char *auth_grpfile;
/* Access Globals*/
int num_sec;
/* number of security directories in access config file */
int num_sec_config;
security_data sec[MAX_SECURITY];
void access_syntax_error(int n, char *err, char *file, FILE *out) {
if(!file) {
fprintf(out,"Syntax error on line %d of access config. file.\n",n);
fprintf(out,"%s\n",err);
exit(1);
}
else {
char e[MAX_STRING_LEN];
sprintf(e,"httpd: syntax error or override violation in access control file %s, reason: %s",file,err);
die(SERVER_ERROR,e,out);
}
}
int parse_access_dir(FILE *f, int line, char or, char *dir,
char *file, FILE *out)
{
char l[MAX_STRING_LEN];
char w[MAX_STRING_LEN];
char w2[MAX_STRING_LEN];
int n=line;
register int x,i;
x = num_sec;
sec[x].opts=OPT_UNSET;
sec[x].override = or;
if(!(sec[x].d = (char *)malloc((sizeof(char)) * (strlen(dir) + 2))))
die(NO_MEMORY,"parse_access_dir",out);
if(is_matchexp(dir))
strcpy(sec[x].d,dir);
else
strcpy_dir(sec[x].d,dir);
sec[x].auth_type = NULL;
sec[x].auth_name = NULL;
sec[x].auth_pwfile = NULL;
sec[x].auth_grpfile = NULL;
for(i=0;i<METHODS;i++) {
sec[x].order[i] = DENY_THEN_ALLOW;
sec[x].num_allow[i]=0;
sec[x].num_deny[i]=0;
sec[x].num_auth[i] = 0;
}
while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
++n;
if((l[0] == '#') || (!l[0])) continue;
cfg_getword(w,l);
if(!strcasecmp(w,"AllowOverride")) {
if(file)
access_syntax_error(n,"override violation",file,out);
sec[x].override = OR_NONE;
while(l[0]) {
cfg_getword(w,l);
if(!strcasecmp(w,"Limit"))
sec[x].override |= OR_LIMIT;
else if(!strcasecmp(w,"Options"))
sec[x].override |= OR_OPTIONS;
else if(!strcasecmp(w,"FileInfo"))
sec[x].override |= OR_FILEINFO;
else if(!strcasecmp(w,"AuthConfig"))
sec[x].override |= OR_AUTHCFG;
else if(!strcasecmp(w,"Indexes"))
sec[x].override |= OR_INDEXES;
else if(!strcasecmp(w,"None"))
sec[x].override = OR_NONE;
else if(!strcasecmp(w,"All"))
sec[x].override = OR_ALL;
else {
access_syntax_error(n,
"Unknown keyword in AllowOverride directive.",file,out);
}
}
}
else if(!strcasecmp(w,"Options")) {
if(!(or & OR_OPTIONS))
access_syntax_error(n,"override violation",file,out);
sec[x].opts = OPT_NONE;
while(l[0]) {
cfg_getword(w,l);
if(!strcasecmp(w,"Indexes"))
sec[x].opts |= OPT_INDEXES;
else if(!strcasecmp(w,"Includes"))
sec[x].opts |= OPT_INCLUDES;
else if(!strcasecmp(w,"IncludesNOEXEC"))
sec[x].opts |= (OPT_INCLUDES | OPT_INCNOEXEC);
else if(!strcasecmp(w,"FollowSymLinks"))
sec[x].opts |= OPT_SYM_LINKS;
else if(!strcasecmp(w,"SymLinksIfOwnerMatch"))
sec[x].opts |= OPT_SYM_OWNER;
else if(!strcasecmp(w,"execCGI"))
sec[x].opts |= OPT_EXECCGI;
else if(!strcasecmp(w,"None"))
sec[x].opts = OPT_NONE;
else if(!strcasecmp(w,"All"))
sec[x].opts = OPT_ALL;
else {
access_syntax_error(n,
"Unknown keyword in Options directive.",file,out);
}
}
}
else if(!strcasecmp(w,"AuthName")) {
if(!(or & OR_AUTHCFG))
access_syntax_error(n,"override violation",file,out);
if(sec[x].auth_name)
free(sec[x].auth_name);
if(!(sec[x].auth_name = strdup(l)))
die(NO_MEMORY,"parse_access_dir",out);
}
else if(!strcasecmp(w,"AuthType")) {
if(!(or & OR_AUTHCFG))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
if(sec[x].auth_type)
free(sec[x].auth_type);
if(!(sec[x].auth_type = strdup(w)))
die(NO_MEMORY,"parse_access_dir",out);
}
else if(!strcasecmp(w,"AuthUserFile")) {
if(!(or & OR_AUTHCFG))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
if(sec[x].auth_pwfile)
free(sec[x].auth_pwfile);
if(!(sec[x].auth_pwfile = strdup(w)))
die(NO_MEMORY,"parse_access_dir",out);
}
else if(!strcasecmp(w,"AuthGroupFile")) {
if(!(or & OR_AUTHCFG))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
if(sec[x].auth_grpfile)
free(sec[x].auth_grpfile);
if(!(sec[x].auth_grpfile = strdup(w)))
die(NO_MEMORY,"parse_access_dir",out);
}
else if(!strcasecmp(w,"AddType")) {
if(!(or & OR_FILEINFO))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0')) {
access_syntax_error(n,
"AddType must be followed by a type, one space, then a file or extension.",
file,out);
}
add_type(w2,w,out);
}
else if(!strcasecmp(w,"DefaultType")) {
if(!(or & OR_FILEINFO))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
strcpy(local_default_type,w);
}
else if(!strcasecmp(w,"AddEncoding")) {
if(!(or & OR_FILEINFO))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0')) {
access_syntax_error(n,
"AddEncoding must be followed by a type, one space, then a file or extension.",
file,out);
}
add_encoding(w2,w,out);
}
else if(!strcasecmp(w,"DefaultIcon")) {
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
strcpy(local_default_icon,w);
}
else if(!strcasecmp(w,"AddDescription")) {
char desc[MAX_STRING_LEN];
int fq;
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
if((fq = ind(l,'\"')) == -1)
access_syntax_error(n,"AddDescription must have quotes",
file,out);
else {
getword(desc,&l[++fq],'\"');
cfg_getword(w,&l[fq]);
add_desc(BY_PATH,desc,w,sec[x].d,out);
}
}
else if(!strcasecmp(w,"IndexIgnore")) {
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
while(l[0]) {
cfg_getword(w,l);
add_ignore(w,sec[x].d,out);
}
}
else if(!strcasecmp(w,"AddIcon")) {
char w2[MAX_STRING_LEN];
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_icon(BY_PATH,w2,w,sec[x].d,out);
}
}
else if(!strcasecmp(w,"AddIconByType")) {
char w2[MAX_STRING_LEN];
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_icon(BY_TYPE,w2,w,sec[x].d,out);
}
}
else if(!strcasecmp(w,"AddIconByEncoding")) {
char w2[MAX_STRING_LEN];
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_icon(BY_ENCODING,w2,w,sec[x].d,out);
}
}
else if(!strcasecmp(w,"ReadmeName")) {
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
add_readme(w,sec[x].d,out);
}
else if(!strcasecmp(w,"HeaderName")) {
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
add_header(w,sec[x].d,out);
}
else if(!strcasecmp(w,"IndexOptions")) {
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
add_opts(l,sec[x].d,out);
}
else if(!strcasecmp(w,"Redirect")) {
if(!(or & OR_FILEINFO))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
access_syntax_error(n,
"Redirect must be followed by a document, one space, then a URL.",file,out);
}
if(!file)
add_redirect(w,w2);
else
access_syntax_error(n,
"Redirect no longer supported from .htaccess files.",file,out);
}
else if(!strcasecmp(w,"<Limit")) {
int m[METHODS];
if(!(or & OR_LIMIT))
access_syntax_error(n,"override violation",file,out);
for(i=0;i<METHODS;i++) m[i] = 0;
getword(w2,l,'>');
while(w2[0]) {
cfg_getword(w,w2);
if(!strcasecmp(w,"GET")) m[M_GET]=1;
else if(!strcasecmp(w,"PUT")) m[M_PUT]=1;
else if(!strcasecmp(w,"POST")) m[M_POST]=1;
else if(!strcasecmp(w,"DELETE")) m[M_DELETE]=1;
}
while(1) {
if(cfg_getline(l,MAX_STRING_LEN,f))
access_syntax_error(n,"Limit missing /Limit",file,out);
n++;
if((l[0] == '#') || (!l[0])) continue;
if(!strcasecmp(l,"</Limit>"))
break;
cfg_getword(w,l);
if(!strcasecmp(w,"order")) {
if(!strcasecmp(l,"allow,deny")) {
for(i=0;i<METHODS;i++)
if(m[i])
sec[x].order[i] = ALLOW_THEN_DENY;
}
else if(!strcasecmp(l,"deny,allow")) {
for(i=0;i<METHODS;i++)
if(m[i])
sec[x].order[i] = DENY_THEN_ALLOW;
}
else if(!strcasecmp(l,"mutual-failure")) {
for(i=0;i<METHODS;i++)
if(m[i])
sec[x].order[i] = MUTUAL_FAILURE;
}
else
access_syntax_error(n,"Unknown order.",file,out);
}
else if((!strcasecmp(w,"allow"))) {
cfg_getword(w,l);
if(strcmp(w,"from"))
access_syntax_error(n,
"allow must be followed by from.",
file,out);
while(1) {
cfg_getword(w,l);
if(!w[0]) break;
for(i=0;i<METHODS;i++)
if(m[i]) {
int q=sec[x].num_allow[i]++;
if(!(sec[x].allow[i][q] = strdup(w)))
die(NO_MEMORY,"parse_access_dir",out);
}
}
}
else if(!strcasecmp(w,"require")) {
for(i=0;i<METHODS;i++)
if(m[i]) {
int q=sec[x].num_auth[i]++;
if(!(sec[x].auth[i][q] = strdup(l)))
die(NO_MEMORY,"parse_access_dir",out);
}
}
else if((!strcasecmp(w,"deny"))) {
cfg_getword(w,l);
if(strcmp(w,"from"))
access_syntax_error(n,
"deny must be followed by from.",
file,out);
while(1) {
cfg_getword(w,l);
if(!w[0]) break;
for(i=0;i<METHODS;i++)
if(m[i]) {
int q=sec[x].num_deny[i]++;
if(!(sec[x].deny[i][q] = strdup(w)))
die(NO_MEMORY,"parse_access_dir",out);
}
}
}
else
access_syntax_error(n,"Unknown keyword in Limit region.",
file,out);
}
}
else if(!strcasecmp(w,"</Directory>"))
break;
else {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"Unknown method %s",w);
access_syntax_error(n,errstr,file,out);
return -1;
}
}
++num_sec;
return n;
}
void parse_htaccess(char *path, char override, FILE *out) {
FILE *f;
char t[MAX_STRING_LEN];
char d[MAX_STRING_LEN];
strcpy(d,path);
make_full_path(d,access_name,t);
if((f=fopen(t,"r"))) {
parse_access_dir(f,-1,override,d,t,out);
fclose(f);
}
}
void process_access_config(FILE *errors) {
FILE *f;
char l[MAX_STRING_LEN];
char w[MAX_STRING_LEN];
int n;
num_sec = 0;
n=0;
if(!(f=fopen(access_confname,"r"))) {
fprintf(errors,"httpd: could not open access configuration file %s.\n",
access_confname);
perror("fopen");
exit(1);
}
while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
++n;
if((l[0] == '#') || (!l[0])) continue;
cfg_getword(w,l);
if(strcasecmp(w,"<Directory")) {
fprintf(errors,
"Syntax error on line %d of access config. file.\n",n);
fprintf(errors,"Unknown directive %s.\n",w);
exit(1);
}
getword(w,l,'>');
n=parse_access_dir(f,n,OR_ALL,w,NULL,errors);
}
fclose(f);
num_sec_config = num_sec;
}
int get_pw(char *user, char *pw, FILE *errors) {
FILE *f;
char errstr[MAX_STRING_LEN];
char l[MAX_STRING_LEN];
char w[MAX_STRING_LEN];
if(!(f=fopen(auth_pwfile,"r"))) {
sprintf(errstr,"Could not open user file %s",auth_pwfile);
die(SERVER_ERROR,errstr,errors);
}
while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
if((l[0] == '#') || (!l[0])) continue;
getword(w,l,':');
if(!strcmp(user,w)) {
strcpy(pw,l);
fclose(f);
return 1;
}
}
fclose(f);
return 0;
}
struct ge {
char *name;
char *members;
struct ge *next;
};
static struct ge *grps;
int init_group(char *grpfile, FILE *out) {
FILE *f;
struct ge *p;
char l[HUGE_STRING_LEN],w[HUGE_STRING_LEN];
if(!(f=fopen(grpfile,"r")))
return 0;
grps = NULL;
while(!(cfg_getline(l,HUGE_STRING_LEN,f))) {
if((l[0] == '#') || (!l[0])) continue;
getword(w,l,':');
if(!(p = (struct ge *) malloc (sizeof(struct ge)))) {
fclose(f);
die(NO_MEMORY,"init_group",out);
}
if(!(p->name = strdup(w))) {
fclose(f);
die(NO_MEMORY,"init_group",out);
}
if(!(p->members = strdup(l))) {
fclose(f);
die(NO_MEMORY,"init_group",out);
}
p->next = grps;
grps = p;
}
fclose(f);
return 1;
}
/* make global for now. This function is called a lot SSG 4/25/95 */
char mems[HUGE_STRING_LEN],wrdbuf[HUGE_STRING_LEN];
int in_group(char *user, char *group) {
struct ge *p = grps;
while(p) {
if(!strcmp(p->name,group)) {
strcpy(mems,p->members);
while(mems[0]) {
getword(wrdbuf,mems,' ');
if(!strcmp(wrdbuf,user))
return 1;
}
}
p=p->next;
}
return 0;
}
void kill_group() {
struct ge *p = grps, *q;
while(p) {
free(p->name);
free(p->members);
q=p;
p=p->next;
free(q);
}
}
void read_config(FILE *errors)
{
reset_aliases();
process_server_config(errors);
init_mime();
init_indexing();
process_resource_config(errors);
process_access_config(errors);
}